package org.drushpal.model
{
	import flash.display.Sprite;
	import flash.net.SharedObject;
	import flash.net.registerClassAlias;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.core.Application;
	import mx.core.FlexGlobals;
	import mx.events.CloseEvent;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	
	import org.drushpal.model.vo.Project;
	import org.drushpal.model.vo.Release;
	import org.drushpal.model.vo.Term;
	import org.robotlegs.mvcs.Actor;

	public class RepositoryModel extends Actor
	{
		public static const DAY:Number = 86400000; //one day is this many milliseconds... google it if you don't believe me
		public static const UPDATE_URL:String = "http://updates.drupal.org/release-history/"; //project-list/all
		
		private var _projects:ArrayCollection;
		[Bindable]
		public var availableProjects:ArrayCollection
		public var lastUpdated:Date;	
		
		private var storageRepo:SharedObject;
		
		public function RepositoryModel()
		{			
			registerClassAlias("Project",Project);
			registerClassAlias("Term",Term);
			registerClassAlias("Release",Release);
			
			checkRepo();
		}
		
		
		private function checkRepo():void{
			storageRepo = SharedObject.getLocal("repository");
			if( storageRepo.size && 
				storageRepo.data && 
				storageRepo.data.projects){
				projects = storageRepo.data.projects;
				lastUpdated = storageRepo.data.lastUpdated;
			}else{
				projects = new ArrayCollection();
			}
			var now:Number = new Date().getTime();
			if(!lastUpdated || 
				(now - lastUpdated.getTime() > DAY)){
				Alert.show("Your project repository is either outdated or missing. Would you like to rebuild it now?","Repository Outdated",Alert.YES|Alert.NO,FlexGlobals.topLevelApplication as Sprite,onRepositoryWarning,null,Alert.YES);
			}	
		}
		
		private function onRepositoryWarning(event:CloseEvent):void{
			if(event.detail == Alert.YES) update();
		}
		public function setBusyCursor():void{
			FlexGlobals.topLevelApplication.cursorManager.setBusyCursor();
		}
		public function removeBusyCursor():void{
			FlexGlobals.topLevelApplication.cursorManager.removeBusyCursor();
		}
		
	
		
		public function relaseHistory(short_name:String,version:String="all"):void{
			var req:HTTPService = new HTTPService();
			req.url = UPDATE_URL+short_name+"/"+version;
			req.resultFormat = "e4x";
			req.addEventListener(ResultEvent.RESULT,onReleaseHistory);
			req.addEventListener(FaultEvent.FAULT,onError);
			setBusyCursor();
			req.send();
		}
		private function onReleaseHistory(event:ResultEvent):void{
			var projectXML:XML =  event.result as XML;
			namespace dc = "http://purl.org/dc/elements/1.1/";
			use namespace dc;
			var test:String = projectXML.short_name;
			var project:Project = getProject(projectXML.short_name);
			project.releases = new Array();
			for each(var releaseXML:XML in projectXML.releases.release){
				var release:Release = new Release();
				release.version = releaseXML.version;
				release.date = new Date();
				release.date.setTime(parseInt(releaseXML.date)*1000);//flex dates are milliseconds, unixtime is regular seconds
				release.download_link=releaseXML.download_link;
				release.filesize=releaseXML.filesize;
				release.mdhash=releaseXML.mdhash;
				release.name=releaseXML.name;
				release.release_link=releaseXML.release_link;
				release.tag=releaseXML.tag;
				release.status=releaseXML.status;
				release.version_extra=releaseXML.version_extra;
				release.version_major=releaseXML.version_major;
				release.terms = new Array();
				for each(var termXML:XML in releaseXML.terms.term){
					var term:Term = new Term();
					term.name = termXML.name;
					term.value = termXML.value;
					release.terms.push(term);
				}
				project.releases.push(release);
			}
			flush();
			removeBusyCursor();
		}
		
		private function onError(event:FaultEvent):void{
			Alert.show("There was a problem accessing update/relase information.","ERROR");
			removeBusyCursor();
		}
		
		public function update():void{
			var req:HTTPService = new HTTPService();
			req.url = UPDATE_URL+"project-list/all";
			req.resultFormat = "e4x";
			req.addEventListener(ResultEvent.RESULT,onUpdate);
			req.addEventListener(FaultEvent.FAULT,onError);
			setBusyCursor();
			req.send();
		}
		private function onUpdate(event:ResultEvent):void{
			lastUpdated = new Date();
			var projectsXML:XML =  event.result as XML;
			projects = new ArrayCollection();
			namespace dc = "http://purl.org/dc/elements/1.1/";
			use namespace dc;
			for each(var projXML:XML in projectsXML.project){
				var project:Project = new Project();
				project.title = projXML.title;
				project.short_name = projXML.short_name;
				project.link = projXML.link;
				project.creator = projXML.creator;
				project.terms = new Array(); 
				for each(var termXML:XML in projXML.terms.term){
					var term:Term = new Term();
					term.name = termXML.name;
					term.value = termXML.value;
					project.terms.push(term);
				}
				project.api_versions = new Array();
				for each(var apiXML:String in projXML.api_versions.api_version){
					project.api_versions.push(apiXML);
				}
				project.status = projXML.project_status;
				_projects.addItem(project);
			}
			removeBusyCursor();
			flush();
			//also, get info on core
			relaseHistory("drupal");
		}
		private function flush():void{
			var storageRepo:SharedObject = SharedObject.getLocal("repository");
			storageRepo.data.projects = _projects;
			storageRepo.data.lastUpdated = lastUpdated;
			storageRepo.flush();
		}
		
		
		public function getProject(short_name:String):Project{
			var proj:Project;
			for each(var project:Project in _projects){
				if(project.short_name == short_name){
					proj=project;
					break;
				}
			}
			return proj;
		}
		
		
		public function get projects():ArrayCollection{
			return _projects;
		}
		public function set projects(value:ArrayCollection):void{
			_projects = value;
			availableProjects = new ArrayCollection();
			for each(var project:Project in _projects){
				//only included published modules or themes in available downloads
				if(project.status == "published" && (project.hasTerm("modules") || project.hasTerm("themes"))){
					availableProjects.addItem(project);
				}
			}
		}
	}
}